<?php
require_once('LuceneXml.class.php');

class PortalReceive
{
    private $_action;
    private $_dataArray;
    private $_data_to_lucene = array();
    private $_db_type;

    public function setData($object)
    {
        $this->_action = $object->action;
        unset($object->action);
        $this->_dataArray = $object;
    }

    public function receive()
    {
        try {
            Model::$dbo['w']->beginTransaction();
            $this->recevieStart();
            Model::$dbo['w']->commit();

            return TRUE;
        } catch (PDOException $e) {
            file_put_contents('/tmp/portal_pdo.txt', print_r($e, 1));
            Model::$dbo['w']->rollback();
            mail(CommonUtils::getAdminMail(), 'PortalReceive error.', print_r($e, 1));

            return FALSE;
        } catch (LUCException $e) {
            file_put_contents('/tmp/portal_luc.txt', print_r($e, 1));
            Model::$dbo['w']->rollback();
            mail(CommonUtils::getAdminMail(), 'PortalReceive error.', print_r($e, 1));

            return FALSE;
        }
    }

    public function recevieStart()
    {
        file_put_contents('/tmp/portal_receive.txt', print_r($this->_dataArray, 1));
        if ($this->_action == 'publish') {
            $this->removeOldValue();
            $this->portalPublish();
        } else {
            $this->portalUnpublish();
        }
        $this->sendXmlToLucene();
    }

    public function sendXmlToLucene()
    {
        $lucene = new LuceneXml;
        foreach ($this->_data_to_lucene as $operation=>$datas) {
            foreach ($datas as $type=>$data) {
                if (!empty($data)) {
                    $data = $this->formateDataLucene($type, $data);
                    $file = $lucene->newLuceneXml($type, $data, $operation);
                    $lucene->addXmlNeedPush($type, $file);
                }
            }
        }
        $lucene->pushXmlToLuceneServer();
    }

    public function portalPublish()
    {
        foreach ($this->_dataArray as $type=>$objects) {
            foreach ($objects as $object) {
                if (!empty($object)) {
                    $this->publish($type, $object);
                }
            }
        }
    }

    public function removeOldValue()
    {
        foreach ($this->_dataArray as $type=>$objects) {
            $this->removeOldValueByType($type, $objects);
        }
    }

    public function removeOldValueByType($type, $objects)
    {
        switch ($type) {
        case 'folder':
            $this->removeOldFolder($objects);
            break;
        case 'folder_video':
            $this->removeOldFolderVideo($objects);
            break;
        case 'folder_image':
            $this->removeOldFolderImage($objects);
            break;
        case 'image':
            $this->removeOldImage($objects);
            break;
        case 'video':
            $this->removeOldVideo($objects);
            break;
        case 'cast':
            $this->removeOldCast($objects);
            break;
        case 'chapter':
            $this->removeOldChapter($objects);
            break;
        case 'info':
            $this->removeOldInfo($objects);
            break;
        }
    }

    public function removeOldFolder($objects)
    {
        if (!empty($objects)) {
            $programme_id = '';
            $episode_id = '';
            $id = array();
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                    $episode_id = $object->episode_id;
                }
                $id[] = $object->id;
            }
            $folder = new folder;
            $folders = $folder->findFolderNotInId($id, $programme_id, $episode_id);
            if (!empty($folders)) {
                foreach ($folders as $folder) {
                    $this->unpublish('folder', $folder);
                }
            }
        }
    }

    public function removeOldFolderVideo($objects)
    {
        if (!empty($objects)) {
            $folder_id = array();
            $video_id = array();
            $programme_id = '';
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                }
                $folder_id[] = $object->folder_id;
                $video_id[] = $object->video_id;
            }

            $folder_video = new folder_video;
            $folder_videos = $folder_video->findFolderVideoNotInId($folder_id, $video_id, $programme_id);
            if (!empty($folder_videos)) {
                foreach ($folder_videos as $folder_video) {
                    $this->unpublish('folder_video', $folder_video);
                } 
            }
        }
    }

    public function removeOldFolderImage($objects)
    {
        if (!empty($objects)) {
            $folder_id = array();
            $image_id = array();
            $programme_id = '';
            $episode_id = '';
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                    $episode_id = $object->episode_id;
                }
                $folder_id[] = $object->folder_id;
                $image_id[] = $object->image_id;
            }

            $folder_image = new folder_image;
            $folder_images = $folder_image->findFolderImageNotInId($folder_id, $image_id, $programme_id, $episode_id);
            if (!empty($folder_images)) {
                foreach ($folder_images as $folder_image) {
                    $this->unpublish('folder_image', $folder_image);
                } 
            }
        }
    }

    public function removeOldImage($objects)
    {
        if (!empty($objects)) {
            $programme_id = '';
            $episode_id = '';
            $id = array();
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                    $episode_id = $object->episode_id;
                }
                $id[] = $object->id;
            }
            $image = new image;
            $images = $image->findFolderNotInId($id, $programme_id, $episode_id);
            if (!empty($images)) {
                foreach ($images as $image) {
                    if (empty($episode_id)) {
                        $this->unpublish('image', $image);
                    } else {
                        $flag_image_exists_in_programme = $this->checkOldImageForProgramme($image->id, $image->programme_id);
                        if ($flag_image_exists_in_programme == FALSE) {
                            $this->unpublish('image', $image);
                        } 
                    }
                }
            }
        }
    }

    public function checkOldImageForProgramme($image_id, $programme_id, $episode_id='0')
    {
        $folder_image = new folder_image;
        $images = $folder_image->findFolderImageByImageId($image_id, $programme_id, $episode_id);
        if (!empty($images)) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    public function removeOldVideo($objects)
    {
        if (!empty($objects)) {
            $programme_id = '';
            $id = array();
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                }
                $id[] = $object->id;
            }
            $video = new video;
            $videos = $video->findVideoNotInId($id, $programme_id);
            if (!empty($videos)) {
                foreach ($videos as $video) {
                    $this->unpublish('video', $video);
                }
            }
        }
    }

    public function removeOldCast($objects)
    {
        return FALSE;

        if (!empty($objects)) {
            $programme_id = '';
            $id = array();
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                }
                $id[] = $object->id;
            }
            $cast = new cast;
            $casts = $cast->findCastNotInId($id, $programme_id);
            if (!empty($casts)) {
                foreach ($casts as $cast) {
                    $this->unpublish('cast', $cast);
                }
            }
        }
    }

    public function removeOldChapter($objects)
    {
        if (!empty($objects)) {
            $programme_id = '';
            $id = array();
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                }
                $id[] = $object->id;
            }
            $chapter = new chapter;
            $chapters = $chapter->findChapterNotInId($id, $programme_id);
            if (!empty($chapters)) {
                foreach ($chapters as $chapter) {
                    $this->unpublish('chapter', $chapter);
                }
            }
        }
    }

    public function removeOldInfo($objects)
    {
        if (!empty($objects)) {
            $id = array();
            $info_type_id = array();
            $programme_id = '';
            $episode_id = '';
            foreach ($objects as $object) {
                if (empty($programme_id)) {
                    $programme_id = $object->programme_id;
                    $episode_id = $object->episode_id;
                }
                $info_id[] = $object->info_id;
                $info_type_id[] = $object->info_type_id;
            }

            $info = new info;
            $infos = $info->findInfoNotInId($info_id, $info_type_id, $programme_id, $episode_id);
            if (!empty($infos)) {
                foreach ($infos as $info) {
                    $this->unpublish('info', $info);
                } 
            }
        }
    }

    public function portalUnpublish()
    {
        //file_put_contents('/tmp/portal_unpublished.txt', print_r($this->_dataArray, 1));
        foreach ($this->_dataArray as $type=>$objects) {
            foreach ($objects as $object) {
                if (!empty($object)) {
                    $this->unpublish($type, $object);
                }
            }
        }
    }

    public function publish($type, $object)
    {
        var_dump($type);
        //file_put_contents('/tmp/portal_'.$type, print_r($object, 1));
        $object_record = new $type;

        switch ($type) {
        case 'folder_video':
            $object_record = $object_record->get(array($object->folder_id, $object->video_id));
            break;
        case 'folder_image':
            $object_record = $object_record->get(array($object->folder_id, $object->image_id));
            break;
        case 'info':
            $object_record = $object_record->get(array($object->info_id, $object->info_type_id));
            break;
        default:
            $object_record = $object_record->get($object->id);
            break;
        }

        if (empty($object_record)) {
            $object_record = new $type;
            $object_record->set($object);
            $object_record->insert($object_record);            
            $operation = 'add';
        } else {
            $object_record->set($object);
            $object_record->update($object_record);
            $operation = 'edit';
        }

        $data = $this->formatData($operation, $type, $object);
        $this->addData($operation, $type, $data);
    }

    public function unpublish($type, $object)
    {
        $operation = 'del';
        $object_record = new $type;
        $object_record->set($object);
        $object_record->delete($object_record);

        $data = $this->formatData($operation, $type, $object);
        $this->addData($operation, $type, $data);
    }

    public function addData($operation, $type, $data)
    {
        $this->_data_to_lucene[$operation][$type][] = $data;
    }

    public function formatData($operation, $type, $object)
    {
        switch ($type) {
        case 'folder_image':
            $data = $this->formateDataFolderImage($operation, $object);
            break;
        case 'folder_video':
            $data = $this->formateDataFolderVideo($operation, $object);
            break;
        case 'info':
            $data = $this->formateDataInfo($operation, $object);
            break;
        default:
            $data = (array) $object;
            break;
        }

        return $data;
    }

    public function formateDataFolderImage($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->folder_id . '_' . $object->image_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->folder_id . '_' . $object->image_id
            );
            break;
        }

        return $data;
    }

    public function formateDataFolderVideo($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->folder_id . '_' . $object->video_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->folder_id . '_' . $object->video_id
            );
            break;
        }

        return $data;
    }

    public function formateDataInfo($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->info_id . '_' . $object->info_type_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->info_id . '_' . $object->info_type_id
            );
            break;
        }

        return $data;
    }

    public function formateDataLucene($type, $data)
    {
        if (empty($this->_db_type[$type])) {
            $this->getDbType($type);
        }

        foreach ($data as $key=>$row) {
            foreach ($row as $field=>$value) {
                if (!isset($this->_db_type[$type][$field]['type'])) {
                    continue;
                }
                switch ($this->_db_type[$type][$field]['type']) {
                case 'datetime':
                    break;
                case 'timestamp':
                    $data[$key][$field] = date('Y-m-d\TH:i:s\Z', (int) $row[$field]);
                    break;
                case 'int':
				case 'bit':
				case 'bigint':
				case 'tinyint':
				case 'smallint':
                    $data[$key][$field] = $row[$field] ? $row[$field] : 0; 
                    break;
                default:
                    break;
                }
            }
        }

        return $data;
    }

    public function getDbType($table_name)
    {
        $sql = "desc ".$table_name;
        $ret = Model::selectBySql($sql);
        foreach ($ret as $row) {
            $this->_db_type[$table_name][strtolower($row['Field'])] = array(
                'type' => preg_replace('/\((?!\)).+\)+/','',$row['Type']),
                'null' => ($row['Null']=='YES'),
                'default' => $row['Default']
            );
        }
    }
}
?>
